package cn.zt.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.db.sql.Order;
import cn.zt.domain.dao.Airline;
import cn.zt.domain.dao.Orders;
import cn.zt.domain.dao.Type;
import cn.zt.domain.dao.User;
import cn.zt.domain.dto.OrderDTO;
import cn.zt.domain.pojo.Result;
import cn.zt.mapper.OrderMapper;
import cn.zt.mapper.SelectMapper;
import cn.zt.mapper.TypeMapper;
import cn.zt.mapper.UserMapper;
import cn.zt.service.IOrderService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Objects;

@Service
public class OrderServiceImpl extends ServiceImpl<OrderMapper, Orders> implements IOrderService {

    @Resource
    private OrderMapper orderMapper;
    @Resource
    private SelectMapper selectMapper;
    @Resource
    private TypeMapper typeMapper;
    @Resource
    private UserMapper userMapper;

    @Override
    @Transactional
    public Result buy(OrderDTO orderDTO){

        User user = userMapper.selectById(orderDTO.getUseUserId());
        if (user == null) {
            return Result.fail("用户不存在");
        }

        if (orderDTO.getFlightId() == null) {
            return Result.fail("航班号不能为空");
        }
        Long flightId = Long.valueOf(orderDTO.getFlightId());
        Airline airline = selectMapper.selectOne(
                new LambdaQueryWrapper<Airline>()
                        .eq(Airline::getId, flightId));

        if (airline == null) {
            return Result.fail("航班不存在");
        }

        //查该航班的舱位余票
        Type type = typeMapper.selectOne(
                new LambdaQueryWrapper<Type>().eq(Type::getFlightId, orderDTO.getFlightId()));
        if (type == null){
            return Result.fail("航班舱位信息不存在");
        }
        int rest = 0;

        if (orderDTO.getClazz() == 1)rest = type.getOneCount();
        if (orderDTO.getClazz() == 2)rest = type.getTwoCount();
        if (orderDTO.getClazz() == 3)rest = type.getThreeCount();

        int totalTickets = airline.getTotalTickets();

        Orders orders = BeanUtil.copyProperties(orderDTO, Orders.class);
        orders.setTickets(1);
        if (rest <= 0) {
            return Result.fail("该航班已无票，是否候补");
        } else if(orderDTO.getTickets() > rest){
            return Result.fail("该航班余票不足，请重新下单");
        }

        orders.setStatus(1);
        orders.setOrderUserId(Long.valueOf(orderDTO.getOrderUserId()));
        orders.setUseUserId(Long.valueOf(orderDTO.getUseUserId()));
        orders.setFlightId(airline.getId());

        //查询用户选择的座位是否合法
        Integer seatId = orderDTO.getSeatId();
        if(seatId <= 0 || seatId > totalTickets){
            return Result.fail("座位不存在");
        }

        //查询用户选择的座位是否已被选择
        Orders seatOrder = orderMapper.selectOne(new LambdaQueryWrapper<Orders>()
                .eq(Orders::getSeatId, seatId)
                .eq(Orders::getFlightId, flightId));

        int ySeatId = seatId;
        if (seatOrder != null) {
            //算法部分 ,比较low
//            List<Orders> flightOrders = orderMapper.selectList(new LambdaQueryWrapper<Orders>()
//                    .eq(Orders::getFlightId, flightId));
//            int n = totalTickets + 10;
//            boolean isBook[] = new boolean[n];
//            for(Orders flightOrder : flightOrders){
//                isBook[flightOrder.getStatus()] = true;
//            }
//            for (int i = 1; i <= totalTickets; i++){
//                if (!isBook[i]){
//                    seatId = i;
//                    break;
//                }
//            }
            // TODO:算法部分 ,使用hash表二次探测查找空座
            List<Orders> flightOrders = orderMapper.selectList(new LambdaQueryWrapper<Orders>()
                    .eq(Orders::getFlightId, flightId));
            int n = totalTickets + 1; // 假设座位编号从 1 到 totalTickets
            boolean isBook[] = new boolean[n];

            // 标记已预订的座位
            for (Orders flightOrder : flightOrders) {
                int seatNumber = flightOrder.getStatus(); // 假设 status 是座位编号
                if (seatNumber >= 1 && seatNumber <= totalTickets) {
                    isBook[seatNumber] = true;
                }
            }
            for (int i = 1; i <= totalTickets; i++) {
                if (!isBook[i]) {
                    seatId = i;
                    break;
                } else {
                    int j = 1;
                    int probeIndex = (i + j * j) % n;
                    while (probeIndex != i) {
                        if (!isBook[probeIndex]) {
                            seatId = probeIndex;
                            break;
                        }
                        j++;
                        probeIndex = (i + j * j) % n;
                    }
                    if (seatId != -1) {
                        break;
                    }
                }
            }
            if (seatId == -1) {
                return Result.fail("没有可用的座位");
            }


            orders.setSeatId(seatId);
            orderMapper.insert(orders);

            rest -= orderDTO.getTickets();
            //更新该航班舱位票余量
            if (orderDTO.getClazz() == 1) type.setOneCount(rest);
            if (orderDTO.getClazz() == 2) type.setTwoCount(rest);
            if (orderDTO.getClazz() == 3) type.setThreeCount(rest);
            typeMapper.updateById(type);

            return Result.fail("座位" + ySeatId + "已被选择，系统重新分配座位号" + seatId);
        }

        orders.setSeatId(seatId);
        orderMapper.insert(orders);

        rest -= orderDTO.getTickets();
        //更新该航班舱位票余量
        if (orderDTO.getClazz() == 1) type.setOneCount(rest);
        if (orderDTO.getClazz() == 2) type.setTwoCount(rest);
        if (orderDTO.getClazz() == 3) type.setThreeCount(rest);
        typeMapper.updateById(type);

        return Result.ok(seatId);
    }

    @Override
    public Result cancel(Long orderId) {
        Orders orders = orderMapper.selectById(orderId);


        if(orders.getStatus() == 2){
            return Result.fail("该订单已退票");
        }

        Date now = new Date();
        Airline airline = selectMapper.selectOne(new LambdaQueryWrapper<Airline>().eq(Airline::getId, orders.getFlightId()));
        Date date = airline.getDate();
        if(now.after(date)){
            return Result.fail("无法退票，该航班已开");
        }

        Type type = typeMapper.selectOne(
                new LambdaQueryWrapper<Type>().eq(Type::getFlightId, orders.getFlightId()));

        orders.setStatus(2);
        orders.setFlightId(airline.getId());
        orderMapper.updateById(orders);

        if(orders.getClazz() == 1) type.setOneCount(type.getOneCount() + orders.getTickets());
        if(orders.getClazz() == 2) type.setTwoCount(type.getTwoCount() + orders.getTickets());
        if(orders.getClazz() == 3) type.setThreeCount(type.getThreeCount() + orders.getTickets());


        //查询当前航班号有无候补
//        List<Orders> waitingOrderList = orderMapper.selectList(
//                new LambdaQueryWrapper<Orders>().eq(Orders::getFlightId, orders.getFlightId())
//                        .eq(Orders :: getClazz, orders.getClazz())
//                        .eq(Orders::getStatus, 0));

        //TODO:算法实现
        List<Orders> waitingOrderList1 = orderMapper.selectList(new LambdaQueryWrapper<Orders>()
                .eq(Orders::getFlightId, orders.getFlightId()));

        List<Orders> waitingOrderList = new ArrayList<>();

        for (Orders waitingOrder : waitingOrderList1) {
            if(waitingOrder.getStatus() == 0){
                waitingOrderList.add(waitingOrder);
            }
        }

        int rest_count = orders.getTickets();
        for (Orders waitingOrder : waitingOrderList) {
            int tickets = waitingOrder.getTickets();
            if(tickets <= rest_count){
                waitingOrder.setStatus(1);
                Orders orders1 = orderMapper.selectById(orders.getId());
                int seatId = orders1.getSeatId();
                waitingOrder.setSeatId(seatId);
                rest_count -= tickets;
//                orders.setFlightId(airline.getId());
                orderMapper.updateById(waitingOrder);
                if(orders.getClazz() == 1) type.setOneCount(type.getOneCount() - orders.getTickets());
                if(orders.getClazz() == 2) type.setTwoCount(type.getTwoCount() - orders.getTickets());
                if(orders.getClazz() == 3) type.setThreeCount(type.getThreeCount() - orders.getTickets());

            }else{
                waitingOrder.setTickets(tickets - rest_count);
                orders.setFlightId(airline.getId());
                orderMapper.updateById(waitingOrder);
                //建一个新的订单
                Orders newOrder = BeanUtil.copyProperties(waitingOrder, Orders.class);
                newOrder.setTickets(rest_count);
                newOrder.setStatus(1);
                int seatId = orderMapper.selectById(orders.getId()).getSeatId();
                waitingOrder.setSeatId(seatId);
                orders.setFlightId(airline.getId());
                orderMapper.insert(newOrder);
                if(orders.getClazz() == 1) type.setOneCount(0);
                if(orders.getClazz() == 2) type.setTwoCount(0);
                if(orders.getClazz() == 3) type.setThreeCount(0);

                break;
            }
        }
        typeMapper.updateById(type);
        return Result.ok("退订成功");
    }

    @Override
    public Result waitForFlight(OrderDTO orderDTO) {
        User user = userMapper.selectById(orderDTO.getUseUserId());
        if (user == null) {
            return Result.fail("身份ID" + orderDTO.getUseUserId() + "不存在");
        }

        if (orderDTO.getFlightId() == null) {
            return Result.fail("航班号不能为空");
        }

        Long flightId;
        try {
            flightId = Long.valueOf(orderDTO.getFlightId());
        } catch (NumberFormatException e) {
            return Result.fail("无效的航班号格式");
        }
        Type type = typeMapper.selectOne(
                new LambdaQueryWrapper<Type>().eq(Type::getFlightId, orderDTO.getFlightId()));

        if (type == null){
            return Result.fail("航班舱位信息不存在");
        }

        int count = 0;
        if (orderDTO.getClazz() == 1) count = type.getOneCount();
        else if (orderDTO.getClazz() == 2) count = type.getTwoCount();
        else if (orderDTO.getClazz() == 3) count = type.getThreeCount();

//        Airline airline = selectMapper.selectOne(new LambdaQueryWrapper<Airline>().eq(Airline::getId, orderDTO.getFlightId()));
//        if (airline == null){
//            return Result.fail("航班号错误");
//        }
        //TODO:算法实现
        List<Airline> airList = selectMapper.selectList(new LambdaQueryWrapper<Airline>());

        Airline airline = new Airline();
        for(Airline air : airList){
            if(Objects.equals(air.getId(), Long.valueOf(orderDTO.getFlightId()))){
                airline = air;
                break;
            }
        }

        Orders orders = BeanUtil.copyProperties(orderDTO, Orders.class);
        if(orderDTO.getTickets() <= count){
//            orders.setStatus(1);
//            orders.setFlightId(airline.getId());
//            orders.setUserId(Long.valueOf(orderDTO.getUserId()));
//            orders.setSeatId(airline.getTotalTickets() - count + 1);
//            orders.setUserId(Long.valueOf(orderDTO.getUserId()));
//            orderMapper.insert(orders);
//            if (orderDTO.getClazz() == 1) type.setOneCount(count - orderDTO.getTickets());
//            if (orderDTO.getClazz() == 2) type.setTwoCount(count - orderDTO.getTickets());
//            if (orderDTO.getClazz() == 3) type.setThreeCount(count - orderDTO.getTickets());
//            typeMapper.updateById(type);
            return Result.fail("尚有余票，请预定");
        }

        orders.setStatus(0);
        orders.setOrderUserId(Long.valueOf(orderDTO.getOrderUserId()));
        orders.setUseUserId(Long.valueOf(orderDTO.getUseUserId()));
        orders.setFlightId(airline.getId());
        orders.setTickets(1);
        orderMapper.insert(orders);
        return Result.ok("候补成功");
    }

}
